﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using ShevaEngine.Core.Modules.Graphics;
using ShevaEngine.Core.Modules.Graphics.Cameras;
using ShevaEngine.Core.Modules.Graphics.Foundation;
using System.IO;

namespace ShevaEngine.Core.Modules.Scenes
{
    /// <summary>
    /// Graphics scene object node.
    /// </summary>
    public class SceneNode  : List<SceneNode>
    {
        /// <summary>Bounding sphere.</summary>
        public BoundingSphere BoundingSphere;

        /// <summary>
        /// Constructor.
        /// </summary>
        public SceneNode()
            : base()
        {        
        }

        /// <summary>
        /// Override Add in rendering pipeline method.
        /// </summary>
        /// <param name="renderingPipeline"></param>
        public virtual bool AddInRenderingPipeline(RenderingPipeline renderingPipeline, Camera camera, Matrix worldMatrix)
        {
            if (this.BoundingSphere.Transform(worldMatrix).Intersects(camera.Frustum))
                for (int i = this.Count - 1; i >= 0; i--)
                    if (this[i].AddInRenderingPipeline(renderingPipeline, camera, worldMatrix))
                        return false;

            return false;
        }

        /// <summary>
        /// Override Add in rendering pipeline method.
        /// </summary>
        /// <param name="renderingPipeline"></param>
        public virtual bool AddInRenderingPipeline(RenderingPipeline renderingPipeline, Vector3 position, float distanceSquared, Matrix worldMatrix)
        {
            if ((Vector3.DistanceSquared(worldMatrix.Translation, position) -
                (this.BoundingSphere.Radius * this.BoundingSphere.Radius)) < distanceSquared)
                for (int i = this.Count - 1; i >= 0; i--)
                    if (this[i].AddInRenderingPipeline(renderingPipeline, position, distanceSquared, worldMatrix))
                        return false;

            return false;
        }

        /// <summary>
        /// Method writes in file.
        /// </summary>
        /// <param name="sw"></param>
        public void WriteInTxt(StreamWriter sw, Int32 indent)
        {
            for (int i = 0; i < indent; i++)
                sw.Write(" ");

            sw.WriteLine(this);

            foreach (SceneNode node in this)
                node.WriteInTxt(sw, indent + 2);
        }

        /// <summary>
        /// Method setups draw call key.
        /// </summary>
        /// <param name="drawCallKey"></param>
        public virtual void SetupDrawCallKey(DrawCallKey drawCallKey)
        {
            foreach (SceneNode item in this)
                item.SetupDrawCallKey(drawCallKey);
        }
    }
}
